package cn.net.autocode.platform.providers.service;

import cn.hutool.core.util.StrUtil;
import cn.net.autocode.core.utils.UserThreadLocalUtils;
import cn.net.autocode.dbManager.Dao;
import cn.net.autocode.dbManager.IdWorker;
import cn.net.autocode.dbManager.handler.PreparedStatementHandler;
import cn.net.autocode.platform.exception.PlatformQueryException;
import cn.net.autocode.platform.providers.rules.InsertRules;
import cn.net.autocode.platform.providers.rules.UpdateRules;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;

@Service
public class SaveServ {

    private final Dao dao;
    private final Dao dictDao;

    public SaveServ(Dao dao,@Qualifier("dictDao") Dao dictDao) {
        this.dao = dao;
        this.dictDao = dictDao;
    }

    public void saveByTableCode(String tableCode,JSONObject data){
        JSONObject table;
        try {
            table = this.tableMsgByTableCode(tableCode);
        } catch (PlatformQueryException e) {
            throw new RuntimeException(e.getMessage());
        }
        String tableName = table.getString("tableName");
        JSONArray rules = this.rules(table.getString("id"));
        JSONArray columnsMsg = this.columnsMsg(table.getString("id"));

        //处理ID
        if(StrUtil.isNotBlank(data.getString("id"))){//更新操作
            int len = this.update(tableName,data,columnsMsg,rules);
            if(len==0){
                throw new RuntimeException("没有找到数据信息，请检查传输参数是否正确!");
            }
        }else{//添加操作
            this.insert(tableName,data,columnsMsg,rules);
        }
    }

    public void saveByTableName(String tableName,JSONObject data){
        JSONObject table;
        try {
            table = this.tableMsgByTableName(tableName);
        } catch (PlatformQueryException e) {
            throw new RuntimeException(e.getMessage());
        }
        JSONArray rules = this.rules(table.getString("id"));
        JSONArray columnsMsg = this.columnsMsg(table.getString("id"));

        //处理ID
        if(StrUtil.isNotBlank(data.getString("id"))){//更新操作
            int len = this.update(tableName,data,columnsMsg,rules);
            if(len==0){
                throw new RuntimeException("没有找到数据信息，请检查传输参数是否正确!");
            }
        }else{//添加操作
            this.insert(tableName,data,columnsMsg,rules);
        }
    }

    public void save(JSONObject data,String tableName,JSONArray columnsMsg,JSONArray rules){
        //处理ID
        if(StrUtil.isNotBlank(data.getString("id"))){//更新操作
            int len = this.update(tableName,data,columnsMsg,rules);
            if(len==0){
                throw new RuntimeException("没有找到数据信息，请检查传输参数是否正确!");
            }
        }else{//添加操作
            this.insert(tableName,data,columnsMsg,rules);
        }
    }

    private void insert(String tableName,JSONObject data,JSONArray columnsMsg,JSONArray rules){

        data.put("id", IdWorker.ulid());

        //获取字段的默认值设置
        InsertRules.defaultValue(columnsMsg,data);

        if(!data.containsKey("orgCode")||data.getString("orgCode")==null||data.getString("orgCode").isBlank()){
            data.put("orgCode", UserThreadLocalUtils.getOrgCode());
        }

        //设置自增字段
        int size=rules.size();
        for(int i=0;i<size;i++){
            JSONObject rule = rules.getJSONObject(i);
            rule.getString("fieldName");
            rule.getString("refColumn");

            int ruleType = rule.getIntValue("ruleType");

            if(ruleType==11){//自增约束
                InsertRules.autoIncrement(rule, data,tableName,dao);
            }
        }

        //必填项校验
        InsertRules.required(columnsMsg,data);

        for(int i=0;i<size;i++){
            JSONObject rule = rules.getJSONObject(i);
            rule.getString("fieldName");
            rule.getString("refColumn");

            int ruleType = rule.getIntValue("ruleType");

            if(ruleType==12){//唯一性约束
                String columnName = rule.getString("fieldName");
                String fieldName = PreparedStatementHandler.columnToProperty(columnName);
                if (data.containsKey(fieldName) && StrUtil.isNotBlank(data.getString(fieldName))){
                    InsertRules.unique(rule, data,tableName,dao);
                }
            }
        }

        //获取插入脚本
        dao.createJSON(data,tableName);
    }

    private int update(String tableName,JSONObject data,JSONArray columnsMsg,JSONArray rules){

        String id = data.getString("id");

        //获取唯一性校验
        List<String> refColumnList = new ArrayList<>();
        int size=rules.size();
        for(int i=0;i<size;i++){
            JSONObject rule = rules.getJSONObject(i);
            int ruleType = rule.getIntValue("ruleType");
            if(ruleType==12){//唯一性约束
                String columnName = rule.getString("fieldName");
                String fieldName = PreparedStatementHandler.columnToProperty(columnName);
                if(data.containsKey(fieldName)){
                    String refColumn = rule.getString("refColumn");
                    if(StrUtil.isNotBlank(refColumn)){
                        JSONArray columns = JSONArray.parseArray(refColumn);
                        for(int j=0;j<columns.size();j++){
                            String refColumnName =  columns.getString(j);
                            if (StrUtil.isNotBlank(refColumnName)) {
                                String refFieldName = PreparedStatementHandler.columnToProperty(refColumnName);
                                refColumnList.add(refFieldName);
                            }
                        }
                    }
                }
            }
        }

        //判断是否需要查询历史数据
        boolean needQuery = false;
        for(String refField:refColumnList){
            if(!data.containsKey(refField)){
                needQuery = true;
                break;
            }
        }

        if(needQuery){
            JSONObject tableData = dao.queryJSON("select * from "+tableName+" where id=?",id);
            for(String refField:refColumnList){
                if(!data.containsKey(refField)){
                    data.put(refField,tableData.get(refField));
                }
            }
        }

        //必填项校验
        UpdateRules.required(columnsMsg,data);

        for(int i=0;i<size;i++){
            JSONObject rule = rules.getJSONObject(i);
            int ruleType = rule.getIntValue("ruleType");
            if(ruleType==12){//唯一性约束
                String columnName = rule.getString("fieldName");
                String fieldName = PreparedStatementHandler.columnToProperty(columnName);
                if (data.containsKey(fieldName) && StrUtil.isNotBlank(data.getString(fieldName))){
                    UpdateRules.unique(rule, data,tableName,dao);
                }
            }
        }
        //获取插入脚本
        return dao.updateJSON(data,tableName);
    }


    public JSONObject tableMsgByTableCode(String tableCode) throws PlatformQueryException {
        JSONObject table = dictDao.queryJSON("select * from ac_table where code=?",tableCode);

        if(table==null||table.isEmpty()){
            throw new PlatformQueryException(tableCode+"对应的表不存在");
        }
        return table;
    }

    public JSONObject tableMsgByTableName(String tableName) throws PlatformQueryException {
        JSONObject table = dictDao.queryJSON("select * from ac_table where table_name=?",tableName);

        if(table==null||table.isEmpty()){
            throw new PlatformQueryException(tableName+"对应的表不存在");
        }
        return table;
    }

    public JSONArray columnsMsg(String tableId) {
        String selectSql = "select * FROM ac_table_fields where table_id=?";
        JSONArray columns = dictDao.queryJSONArray(selectSql,tableId);

        int cols = columns.size();
        for(int col = 0; col < cols; col++) {
            JSONObject json = columns.getJSONObject(col);
            String columnName = json.getString("name").toLowerCase();
            String fieldName = PreparedStatementHandler.columnToProperty(columnName);
            json.put("columnName",columnName);
            json.put("fieldName",fieldName);
        }
        return columns;
    }

    public JSONArray rules(String tableId) {
        return dictDao.queryJSONArray("select * from ac_table_rules where rule_type in (11,12,13) and table_id=?", tableId);
    }
}
